Tạo ứng dụng kiểm tra quyền truy cập trong Android Studio

Trong bài viết này, chúng ta sẽ cùng nhau xây dựng một ứng dụng kiểm tra quyền đơn giản bằng Android Studio và Kotlin, giúp bạn liệt kê các ứng dụng theo quyền truy cập mà chúng đã được cấp trên thiết bị của mình.

Trong thời đại mà các ứng dụng di động ngày càng yêu cầu nhiều quyền truy cập vào dữ liệu cá nhân, việc kiểm soát các quyền này trở nên cực kỳ quan trọng. Tuy nhiên, hệ điều hành Android không cung cấp sẵn một tính năng dễ dàng để kiểm tra các quyền mà ứng dụng đã được cấp. 

Tạo ứng dụng kiểm tra quyền truy cập trong Android Studio

Để bắt đầu, hãy mở một dự án Android Studio mới và tạo một tệp bố cục trong tệp activity_main.xml của bạn.

Nếu bạn không muốn thiết kế giao diện riêng, hãy thoải mái sao chép mã mà chúng tôi cung cấp vì mục đích của bài viết này không phải là để dạy bạn thiết kế giao diện!

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical">

    <Spinner
        android:layout_width="match_parent"
        android:id="@+id/spinner"
        android:padding="4dp"
       
        android:layout_margin="8sp"
        android:layout_marginBottom="8sp"
        android:layout_height="?attr/actionBarSize"/>

    <TextView
        android:layout_width="match_parent"
        android:id="@+id/tvCount"
        android:layout_margin="8sp"
        android:textSize="20sp"
        android:layout_height="wrap_content"/>

    <androidx.recyclerview.widget.RecyclerView
        android:id="@+id/rv_main_list"
        android:layout_margin="4dp"
        android:layout_width="match_parent"
        android:layout_height="match_parent"/>

</LinearLayout>

Trước khi chúng ta chuyển sang hoạt động chính, hãy tạo một tệp item_layout.xml, tệp này sẽ thông báo cho RecyclerView về kiểu bố cục mà chúng ta muốn hiển thị trong danh sách. Chúng ta sẽ thiết kế một bố cục đơn giản bao gồm tên ứng dụng cùng với biểu tượng tương ứng của nó.

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:padding="8sp"
    xmlns:tools="http://schemas.android.com/tools"
    android:orientation="vertical">

    <ImageView
        android:layout_width="50dp"
        android:id="@+id/iv_icon"
        android:src="@mipmap/ic_launcher_round"
        android:layout_height="50dp"/>

    <TextView
        android:layout_width="wrap_content"
        tools:text="app name"
        android:id="@+id/tv_appname"
        android:layout_toEndOf="@id/iv_icon"
        android:textSize="20sp"
        android:layout_centerVertical="true"
        android:layout_marginStart="20dp"
        android:layout_height="wrap_content"/>

</RelativeLayout>

Triển khai

Giờ hãy chuyển đến phần thú vị! Trước khi chuyển sang hoạt động chính, chúng ta cần tạo một lớp dữ liệu cho ứng dụng của mình. Lớp này sẽ cho phép chúng ta truyền cả tên ứng dụng và biểu tượng vào lớp Adapter.

Nếu bạn chưa quen với lớp dữ liệu, chúng là những lớp với các phương thức gettersetter đã được tích hợp sẵn.

data class AppName(val packageName: String, val appName: String, val appIcon: Drawable)

Bây giờ, khi mọi thứ đã được chuẩn bị, chúng ta đã sẵn sàng bắt đầu với hoạt động chính! Đầu tiên, chúng ta sẽ khai báo một số biến sẽ được khởi tạo sau.

Thêm mã sau vào ngay phía trên phương thức onCreate() trong tệp MainActivity.kt:

lateinit var permissionsArray: ArrayList<String>
lateinit var appPackageName: String
lateinit var appName: String
lateinit var appInfo: ApplicationInfo
lateinit var appIcon: Drawable
lateinit var adapter: AppAdapter
lateinit var packages: MutableList<PackageInfo>
private val appList = mutableListOf<AppName>()
private val cameraList = mutableListOf<AppName>()
private val contactsList = mutableListOf<AppName>()
private val locationList = mutableListOf<AppName>()
private val microphoneList = mutableListOf<AppName>()
private val storagemediaList = mutableListOf<AppName>()
private val smsList = mutableListOf<AppName>()

Trong mã của chúng ta, có một số danh sách cho các loại quyền khác nhau như Máy ảnh, Vị trí, Danh bạ, v.v. Tiếp theo, trong phương thức onCreate(), chúng ta sẽ khởi tạo Spinner với permissionsArray và một spinner adapter:

permissionsArray = arrayListOf(
    "Tất cả ứng dụng",
    "Máy ảnh",
    "Danh bạ",
    "Vị trí",
    "Microphone",
    "Bộ nhớ & Phương tiện",
    "SMS"
)

val arrayAdapter = ArrayAdapter(
    this,
    android.R.layout.simple_spinner_dropdown_item,
    permissionsArray
)

spinner.adapter = arrayAdapter

Tiếp theo, chúng ta sẽ khởi tạo danh sách các gói packages với tất cả các ứng dụng đã được cài đặt trên thiết bị:

packages = packageManager.getInstalledPackages(PackageManager.GET_META_DATA)

Mã trên sẽ trả về một danh sách tất cả các gói đã cài đặt trên ứng dụng của chúng ta. Tuy nhiên, chúng ta cũng muốn lọc danh sách này dựa trên quyền được chọn.

Để làm điều này, chúng ta sẽ chạy một vòng lặp for để gán danh sách gói cho appList:

for (i in 0 until packages.size) {
    appPackageName = packages[i].packageName
    appInfo = packageManager.getApplicationInfo(appPackageName, 0)
    appName = packageManager.getApplicationLabel(appInfo) as String
    appIcon = packageManager.getApplicationIcon(appPackageName)

    if (packageManager.getLaunchIntentForPackage(appPackageName) != null) {
        appList.add(AppName(appPackageName, appName, appIcon))
    }
}

Tiếp theo, chúng ta sẽ tạo một hàm để kiểm tra quyền của máy ảnh và các quyền khác tương tự như thế này:

private fun checkCameraPermission(appPackageName: String?): Boolean {
    return PackageManager.PERMISSION_GRANTED == packageManager.checkPermission(
        android.Manifest.permission.CAMERA,
        appPackageName
    )
}

private fun checkLocationPermission(appPackageName: String?): Boolean {
    return (PackageManager.PERMISSION_GRANTED == packageManager.checkPermission(
        android.Manifest.permission.ACCESS_FINE_LOCATION,
        appPackageName
    )) or (PackageManager.PERMISSION_GRANTED == packageManager.checkPermission(
        android.Manifest.permission.ACCESS_COARSE_LOCATION,
        appPackageName
    ))
}

Cuối cùng, chúng ta sẽ thực hiện bộ chọn mục onItemSelectedListener() cho spinner và kết hợp RecyclerView để hiển thị các danh sách ứng dụng theo quyền truy cập.

spinner.onItemSelectedListener = object : OnItemSelectedListener {
    override fun onItemSelected(
        parentView: AdapterView<*>?,
        selectedItemView: View,
        position: Int,
        id: Long
    ) {
        val text = parentView?.getItemAtPosition(position).toString()
        when (text) {
            permissionsArray[0] -> {    // Tất cả ứng dụng
                adapter = AppAdapter(appList, applicationContext)
                rv_main_list.adapter = adapter
                tvCount.text = "${appList.size} ứng dụng tìm thấy"
            }
            permissionsArray[1] -> {    // Máy ảnh
                adapter = AppAdapter(cameraList, applicationContext)
                rv_main_list.adapter = adapter
                tvCount.text = "${cameraList.size} ứng dụng tìm thấy"
            }
            permissionsArray[2] -> {    // Danh bạ
                adapter = AppAdapter(contactsList, applicationContext)
                rv_main_list.adapter = adapter
                tvCount.text = "${contactsList.size} ứng dụng tìm thấy"
            }
            // Tương tự với các quyền khác...
        }
    }

    override fun onNothingSelected(parentView: AdapterView<*>?) {
        // Mã của bạn ở đây
    }
}

Để hoàn thành, bạn cần triển khai lớp AppAdapter cho RecyclerView:

class AppAdapter(
    val items: MutableList<AppName>,
    val context: Context
) : RecyclerView.Adapter<AppAdapter.ViewHolder>() {
    override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ViewHolder {
        return ViewHolder(LayoutInflater.from(context).inflate(R.layout.item_layout, parent, false))
    }

    override fun getItemCount() = items.size

    override fun onBindViewHolder(holder: ViewHolder, position: Int) {
        holder.appName.text = items[position].appName
        holder.icon.setImageDrawable(items[position].appIcon)
    }

    class ViewHolder(itemView: View) : RecyclerView.ViewHolder(itemView) {
        val icon: ImageView = itemView.iv_icon
        val appName = itemView.tv_appname
    }
}

Vậy là xong! Nếu bạn đã thực hiện mọi thứ đúng cách, ứng dụng của bạn sẽ hoạt động.

Chúc mừng bạn! Bạn đã thành công trong việc tạo ứng dụng kiểm tra quyền truy cập của riêng mình bằng Kotlin và Android Studio.